//
//  ViewController.swift
//  ARKit2D
//
//  Created by 4DAGE on 2018/2/10.
//  Copyright © 2018年 zuohua. All rights reserved.
//

import UIKit
import SceneKit
import ARKit
import Vision
//import ZipArchive

class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {
    
    
    //    https://ojyvfkg1d.qnssl.com/cup.scnassets.zip
    //    https://ojyvfkg1d.qnssl.com/vase.scnassets.zip
    //    https://ojyvfkg1d.qnssl.com/candle.scnassets.zip
    // MARK: - Properties
    
    @IBOutlet var sceneView: ARSCNView!
    
    // 原来
    var detectedDataAnchor: ARAnchor?
    var model : SCNScene?
    lazy var detecteAnchors = [String : ARAnchor]()
    lazy var models = [String : SCNScene]()
    var saveP : String?
    var processing = false
    
    // ================================================================================================================================
    // 沙盒路径
    let documentPath:String = NSHomeDirectory() + "/Documents"
    // 沙盒文件数组
    var localFiles : [String] = {
        do {
            let files = try FileManager.default.contentsOfDirectory(atPath: NSHomeDirectory() + "/Documents")
            let results = files.map({
                $0.replacingOccurrences(of: ".scnassets", with: "")
            })
            return results
        }
        catch {
            return [String]()
        }
    }()
    // 负责下载的会话中心
    lazy var urlSession = URLSession(configuration: URLSessionConfiguration.default)
    // ================================================================================================================================
    
    
    // MARK: - View Setup
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Set the session's delegate
        sceneView.session.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()
        
        // Enable horizontal plane detection
        configuration.planeDetection = .horizontal
        
        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }
    
    
    // MARK: 自己加入的方法
    func didFileDownload(name: String) -> Bool {
        for fileName in localFiles {
            if (fileName.contains(name)) {
                print("返回真")
                return true
            }
            continue
        }
        return false
    }
    
    // MARK: - ARSessionDelegate
    
    public func session(_ session: ARSession, didUpdate frame: ARFrame) {
        
        // Only run one Vision request at a time
        if self.processing {
            return
        }
        
        self.processing = true
        
        // Create a Barcode Detection Request
        let request = VNDetectBarcodesRequest { (request, error) in
            
            // Get the first result out of the results, if there are any
            if let results = request.results, let result = results.first as? VNBarcodeObservation {
                
                // Get the bounding box for the bar code and find the center
                var rect = result.boundingBox
                
                // Flip coordinates
                rect = rect.applying(CGAffineTransform(scaleX: 1, y: -1))
                rect = rect.applying(CGAffineTransform(translationX: 0, y: 1))
                
                // Get center
                let center = CGPoint(x: rect.midX, y: rect.midY)
                
                let downloadUrl = result.payloadStringValue
                
                guard let name = downloadUrl?.modelName() else {
                    return
                }
                print("文件名 \(String(describing: name))")
                
                //                if (!self.didFileDownload(name: name)) {
                //                    print("下载 \(name)")
                //                    let urlRequest = URLRequest.init(url: URL.init(string: downloadUrl!)!)
                //                    self.detecteAnchors[name] = nil
                //                    let downloadTask = self.urlSession.downloadTask(with: urlRequest, completionHandler: { (location:URL?, response:URLResponse?, error:Error?)
                //                        -> Void in
                //
                //                        if (error == nil) {
                //                            let locationPath = location!.path
                //                            //                try! FileManager.default.moveItem(atPath: locationPath, toPath: documnets)
                //                            let success = SSZipArchive.unzipFile(atPath: locationPath, toDestination: self.documentPath)
                //                            print("new location:\(locationPath) ===== \(success)")
                //
                //                        }else {
                //                            print(error)
                //                        }
                //                    })
                //                    downloadTask.resume()
                //                    self.localFiles.append(name)
                //                }
                
                
                if(self.models[name] == nil) {
                    let modelName = name + ".scn"
                    let modelPath = "Models.scnassets/" + name
                    let newModel = SCNScene(named: modelName, inDirectory: modelPath)
                    self.models.updateValue(newModel!, forKey: name)
                }
                
                
                // Go back to the main thread
                // 通过HitTest记录二维码的位置
                DispatchQueue.main.async {
                    
                    // Perform a hit test on the ARFrame to find a surface
                    let hitTestResults = frame.hitTest(center, types: [.featurePoint/*, .estimatedHorizontalPlane, .existingPlane, .existingPlaneUsingExtent*/] )
                    
                    // If we have a result, process it
                    if let hitTestResult = hitTestResults.first {
                        
                        if let anchor = self.detecteAnchors[name],
                            let node = self.sceneView.node(for: anchor) {
                            node.transform = SCNMatrix4(hitTestResult.worldTransform)
                        }else {
                            let newAnchor = ARAnchor(transform: hitTestResult.worldTransform)
                            self.sceneView.session.add(anchor: newAnchor)
                            self.detecteAnchors.updateValue(newAnchor, forKey: name)
                        }
                        
                        //                        // If we already have an anchor, update the position of the attached node
                        //                        if let detectedDataAnchor = self.detectedDataAnchor,
                        //                            let node = self.sceneView.node(for: detectedDataAnchor) {
                        //
                        //                                node.transform = SCNMatrix4(hitTestResult.worldTransform)
                        //
                        //                        } else {
                        //                            // Create an anchor. The node will be created in delegate methods
                        //                            self.detectedDataAnchor = ARAnchor(transform: hitTestResult.worldTransform)
                        //                            self.sceneView.session.add(anchor: self.detectedDataAnchor!)
                        //                        }
                    }
                    
                    // Set processing flag off
                    self.processing = false
                }
                
            } else {
                // Set processing flag off
                self.processing = false
            }
        }
        
        // Process the request in the background
        DispatchQueue.global(qos: .userInitiated).async {
            do {
                // Set it to recognize QR code only
                request.symbologies = [.QR]
                
                // Create a request handler using the captured image from the ARFrame
                let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: frame.capturedImage,
                                                                options: [:])
                // Process the request
                try imageRequestHandler.perform([request])
            } catch {
                
            }
        }
    }
    
    // MARK: - ARSCNViewDelegate
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        
        // 检查锚点是否对应数组
        let anchorID = anchor.identifier
        for (name, aranchor) in self.detecteAnchors {
            
            if(aranchor.identifier == anchorID){
                
                
                guard let virtualObjectScene = self.models[name] else {
                    print("空空空空空空空空空 \(name)")
                    return nil
                }
                
                /*
                 let modelName = name + ".scn"
                 let virtualObject = SCNScene(named: name, inDirectory: name.modelPath())
                 //try? SCNScene(url: URL.init(string: modelName)!, options: [:])
                 guard let virtualObjectScene = virtualObject else { //SCNScene(named: modelName, inDirectory: name.modelPath()
                 print("空空空空空空空空空 \(modelName)")
                 return nil
                 }
                 */
                
                let wrapperNode = SCNNode()
                print("显示了")
                for child in virtualObjectScene.rootNode.childNodes {
                    child.geometry?.firstMaterial?.lightingModel = .physicallyBased
                    child.movabilityHint = .movable
                    wrapperNode.addChildNode(child)
                }
                
                // Set its position based off the anchor
                wrapperNode.transform = SCNMatrix4(anchor.transform)
                
                return wrapperNode
            }
            continue;
        }
        
        // If this is our anchor, create a node
        //        if self.detectedDataAnchor?.identifier == anchor.identifier {
        //
        //            // Create a 3D Cup to display
        //            guard let virtualObjectScene = SCNScene(named: "cup.scn", inDirectory: "Models.scnassets/cup") else {
        //                return nil
        //            }
        //            var virtualObjectScene : SCNScene?
        //            if(self.model == nil) {
        //                virtualObjectScene = SCNScene(named: "cup.scn", inDirectory: "Models.scnassets/cup")
        //                print("这里是本地的")
        //            }else {
        //                virtualObjectScene = self.model
        //            }
        //
        //            guard let object = virtualObjectScene else { return nil }
        //            let wrapperNode = SCNNode()
        //
        //            for child in object.rootNode.childNodes {
        //                child.geometry?.firstMaterial?.lightingModel = .physicallyBased
        //                child.movabilityHint = .movable
        //                wrapperNode.addChildNode(child)
        //            }
        //
        //            // Set its position based off the anchor
        //            wrapperNode.transform = SCNMatrix4(anchor.transform)
        //
        //            return wrapperNode
        //        }
        
        return nil
    }
}

extension String {
    // 取出模型名字
    func modelName() ->String {
        let result = self.replacingOccurrences(of:"https://ojyvfkg1d.qnssl.com/", with: "")
        let name = result.replacingOccurrences(of: ".scnassets.zip", with: "")
        return name
    }
    
    func modelPath() ->String {
        let path = NSHomeDirectory() + "/Documents/" + self + ".scnassets"
        return path
    }
}

